home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / ip / ka9q / alpha.arc / AX25SUBR.C < prev    next >
C/C++ Source or Header  |  1988-07-24  |  11KB  |  460 lines

  1. #include "global.h"
  2. #include "mbuf.h"
  3. #include "timer.h"
  4. #include "ax25.h"
  5. #include "lapb.h"
  6. #include <ctype.h>
  7.  
  8. struct ax25_cb *ax25_cb[NHASH];
  9.  
  10. /* Default AX.25 parameters */
  11. int16 t1init = 10000 / MSPTICK;    /* FRACK of 10 seconds */
  12. int16 t2init = 1000 / MSPTICK;    /* 1 sec acknowledgment delay */
  13. int16 t3init = 0 / MSPTICK;    /* No keep-alive polling */
  14. int16 maxframe = 1;        /* Stop and wait */
  15. int16 n2 = 10;            /* 10 retries */
  16. int16 axwindow = 2048;        /* 2K incoming text before RNR'ing */
  17. int16 paclen = 256;        /* 256-byte I fields */
  18. int16 pthresh = 128;        /* Send polls for packets larger than this */
  19.  
  20. /* Address hash function. Exclusive-ORs each byte, ignoring
  21.  * such insignificant, annoying things as E and H bits
  22.  */
  23. static
  24. int16
  25. ax25hash(s)
  26. struct ax25_addr *s;
  27. {
  28.     register char x;
  29.     register int i;
  30.     register char *cp;
  31.  
  32.     x = 0;
  33.     cp = s->call;
  34.     for(i=ALEN; i!=0; i--)
  35.         x ^= *cp++ & 0xfe;
  36.     x ^= s->ssid & SSID;
  37.     return uchar(x) % NHASH;
  38. }
  39. /* Look up entry in hash table */
  40. struct ax25_cb *
  41. find_ax25(addr)
  42. register struct ax25_addr *addr;
  43. {
  44.     int16 hashval;
  45.     register struct ax25_cb *axp;
  46.     char i_state;
  47.  
  48.     /* Find appropriate hash chain */
  49.     hashval = ax25hash(addr);
  50.  
  51.     /* Search hash chain */
  52.     i_state = disable();
  53.     for(axp = ax25_cb[hashval]; axp != NULLAX25; axp = axp->next){
  54.         if(addreq(&axp->addr.dest,addr)){
  55.             restore(i_state);
  56.             return axp;
  57.         }
  58.     }
  59.     restore(i_state);
  60.     return NULLAX25;
  61. }
  62.  
  63. /* Remove address entry from hash table */
  64. del_ax25(axp)
  65. register struct ax25_cb *axp;
  66. {
  67.     int16 hashval;
  68.     char i_state;
  69.  
  70.     if(axp == NULLAX25)
  71.         return;
  72.     /* Remove from hash header list if first on chain */
  73.     hashval = ax25hash(&axp->addr.dest);
  74.     i_state = disable();
  75.  
  76.     /* Remove from chain list */
  77.     if(ax25_cb[hashval] == axp)
  78.         ax25_cb[hashval] = axp->next;
  79.     if(axp->prev != NULLAX25)
  80.         axp->prev->next = axp->next;
  81.     if(axp->next != NULLAX25)
  82.         axp->next->prev = axp->prev;
  83.  
  84.     /* Timers should already be stopped, but just in case... */
  85.     stop_timer(&axp->t1);
  86.     stop_timer(&axp->t2);
  87.     stop_timer(&axp->t3);
  88.  
  89.     /* Free allocated resources */
  90.     free_q(&axp->txq);
  91.     free_q(&axp->rxasm);
  92.     free_q(&axp->rxq);
  93.     free((char *)axp);
  94.  
  95.     restore(i_state);
  96. }
  97.  
  98. /* Create an ax25 control block. Allocate a new structure, if necessary,
  99.  * and fill it with all the defaults. The caller
  100.  * is still responsible for filling in the reply address
  101.  */
  102. struct ax25_cb *
  103. cr_ax25(addr)
  104. struct ax25_addr *addr;
  105. {
  106.     void recover(),send_ack(),pollthem(),ax_incom();
  107.     register struct ax25_cb *axp;
  108.     int16 hashval;
  109.     char i_state;
  110.  
  111.     if(addr == NULLAXADDR)
  112.         return NULLAX25;
  113.  
  114.     if((axp = find_ax25(addr)) == NULLAX25){
  115.         /* Not already in table; create an entry
  116.          * and insert it at the head of the chain
  117.          */
  118.         /* Find appropriate hash chain */
  119.         hashval = ax25hash(addr);
  120.         i_state = disable();
  121.         axp = (struct ax25_cb *)calloc(1,sizeof(struct ax25_cb));
  122.         if(axp == NULLAX25)
  123.             return NULLAX25;
  124.         /* Insert at beginning of chain */
  125.         axp->prev = NULLAX25;
  126.         axp->next = ax25_cb[hashval];
  127.         if(axp->next != NULLAX25)
  128.             axp->next->prev = axp;
  129.         ax25_cb[hashval] = axp;
  130.         restore(i_state);
  131.     }
  132.     axp->maxframe = maxframe;
  133.     axp->window = axwindow;
  134.     axp->paclen = paclen;
  135.     axp->proto = V2;    /* Default, can be changed by other end */
  136.     axp->pthresh = pthresh;
  137.     axp->n2 = n2;
  138.     axp->t1.start = t1init;
  139.     axp->t1.func = recover;
  140.     axp->t1.arg = (char *)axp;
  141.  
  142.     axp->t2.start = t2init;
  143.     axp->t2.func = send_ack;
  144.     axp->t2.arg = (char *)axp;
  145.  
  146.     axp->t3.start = t3init;
  147.     axp->t3.func = pollthem;
  148.     axp->t3.arg = (char *)axp;
  149.  
  150.     axp->r_upcall = ax_incom;
  151.     return axp;
  152. }
  153.  
  154. /*
  155.  * setcall - convert callsign plus substation ID of the form
  156.  * "KA9Q-0" to AX.25 (shifted) address format
  157.  *   Address extension bit is left clear
  158.  *   Return -1 on error, 0 if OK
  159.  */
  160. int
  161. setcall(out,call)
  162. struct ax25_addr *out;
  163. char *call;
  164. {
  165.     int csize;
  166.     unsigned ssid;
  167.     register int i;
  168.     register char *cp,*dp;
  169.     char c;
  170.  
  171.     if(out == (struct ax25_addr *)NULL || call == NULLCHAR || *call == '\0'){
  172.         return -1;
  173.     }
  174.     /* Find dash, if any, separating callsign from ssid
  175.      * Then compute length of callsign field and make sure
  176.      * it isn't excessive
  177.      */
  178.     dp = index(call,'-');
  179.     if(dp == NULLCHAR)
  180.         csize = strlen(call);
  181.     else
  182.         csize = dp - call;
  183.     if(csize > ALEN)
  184.         return -1;
  185.     /* Now find and convert ssid, if any */
  186.     if(dp != NULLCHAR){
  187.         dp++;    /* skip dash */
  188.         ssid = atoi(dp);
  189.         if(ssid > 15)
  190.             return -1;
  191.     } else
  192.         ssid = 0;
  193.     /* Copy upper-case callsign, left shifted one bit */
  194.     cp = out->call;
  195.     for(i=0;i<csize;i++){
  196.         c = *call++;
  197.         if(islower(c))
  198.             c = toupper(c);
  199.         *cp++ = c << 1;
  200.     }
  201.     /* Pad with shifted spaces if necessary */
  202.     for(;i<ALEN;i++)
  203.         *cp++ = ' ' << 1;
  204.     
  205.     /* Insert substation ID field and set reserved bits */
  206.     out->ssid = 0x60 | (ssid << 1);
  207.     return 0;
  208. }
  209. /* Set a digipeater string in an ARP table entry */
  210. setpath(out,in,cnt)
  211. char *out;    /* Target char array containing addresses in net form */
  212. char *in[];    /* Input array of tokenized callsigns in ASCII */
  213. int cnt;    /* Number of callsigns in array */
  214. {
  215.     struct ax25_addr addr;
  216.     char *putaxaddr();
  217.  
  218.     if(cnt == 0)
  219.         return;
  220.     while(cnt-- != 0){
  221.         setcall(&addr,*in++);
  222.         addr.ssid &= ~E;
  223.         out = putaxaddr(out,&addr);
  224.     }
  225.     out[-1] |= E;
  226. }
  227. addreq(a,b)
  228. register struct ax25_addr *a,*b;
  229. {
  230.     if(memcmp(a->call,b->call,ALEN) != 0)
  231.         return 0;
  232.     if((a->ssid & SSID) != (b->ssid & SSID))
  233.         return 0;
  234.     return 1;
  235. }
  236. /* Convert encoded AX.25 address to printable string */
  237. pax25(e,addr)
  238. char *e;
  239. struct ax25_addr *addr;
  240. {
  241.     register int i;
  242.     char c,*cp;
  243.  
  244.     cp = addr->call;
  245.     for(i=ALEN;i != 0;i--){
  246.         c = (*cp++ >> 1) & 0x7f;
  247.         if(c == ' ')
  248.             break;
  249.         *e++ = c;
  250.     }
  251.     if ((addr->ssid & SSID) != 0)
  252.         sprintf(e,"-%d",(addr->ssid >> 1) & 0xf);    /* ssid */
  253.     else
  254.         *e = 0;
  255. }
  256. /* Print a string of AX.25 addresses in the form
  257.  * "KA9Q-0 [via N4HY-0,N2DSY-2]"
  258.  * Designed for use by ARP - arg is a char string
  259.  */
  260. psax25(e,addr)
  261. register char *e;
  262. register char *addr;
  263. {
  264.     int i;
  265.     struct ax25_addr axaddr;
  266.     char tmp[16];
  267.     char *getaxaddr();
  268.  
  269.     e[0] = '\0';    /* Give strcat a staritng point */
  270.     for(i=0;;i++){
  271.         /* Create local copy in host-format structure */
  272.         addr = getaxaddr(&axaddr,addr);
  273.  
  274.         /* Create ASCII representation and append to output */
  275.         pax25(tmp,&axaddr);
  276.         strcat(e,tmp);
  277.  
  278.         if(axaddr.ssid & E)
  279.             break;
  280.         if(i == 0)
  281.             strcat(e," via ");
  282.         else
  283.             strcat(e,",");
  284.         /* Not really necessary, but speeds up subsequent strcats */
  285.         e += strlen(e);
  286.     }
  287. }
  288. static
  289. char *
  290. getaxaddr(ap,cp)
  291. register struct ax25_addr *ap;
  292. register char *cp;
  293. {
  294.     memcpy(ap->call,cp,ALEN);
  295.     cp += ALEN;
  296.     ap->ssid = *cp++;
  297.     return cp;
  298. }
  299. static char *
  300. putaxaddr(cp,ap)
  301. register char *cp;
  302. register struct ax25_addr *ap;
  303. {
  304.     memcpy(cp,ap->call,ALEN);
  305.     cp += ALEN;
  306.     *cp++ = ap->ssid;
  307.     return cp;
  308. }
  309.  
  310. /* Convert a host-format AX.25 header into a mbuf ready for transmission */
  311. struct mbuf *
  312. htonax25(hdr,data)
  313. register struct ax25 *hdr;
  314. struct mbuf *data;
  315. {
  316.     struct mbuf *bp;
  317.     register char *cp;
  318.     register int16 i;
  319.  
  320.     if(hdr == (struct ax25 *)NULL || hdr->ndigis > MAXDIGIS)
  321.         return NULLBUF;
  322.  
  323.     /* Allocate space for return buffer */
  324.     i = AXALEN * (2 + hdr->ndigis);
  325.     if((bp = pushdown(data,i)) == NULLBUF)
  326.         return NULLBUF;
  327.  
  328.     /* Now convert */
  329.     cp = bp->data;
  330.  
  331.     hdr->dest.ssid &= ~E;    /* Dest E-bit is always off */
  332.     /* Encode command/response in C bits */
  333.     switch(hdr->cmdrsp){
  334.     case COMMAND:
  335.         hdr->dest.ssid |= C;
  336.         hdr->source.ssid &= ~C;
  337.         break;
  338.     case RESPONSE:
  339.         hdr->dest.ssid &= ~C;
  340.         hdr->source.ssid |= C;
  341.         break;
  342.     default:
  343.         hdr->dest.ssid &= ~C;
  344.         hdr->source.ssid &= ~C;
  345.         break;
  346.     }
  347.     cp = putaxaddr(cp,&hdr->dest);
  348.  
  349.     /* Set E bit on source address if no digis */
  350.     if(hdr->ndigis == 0){
  351.         hdr->source.ssid |= E;
  352.         putaxaddr(cp,&hdr->source);
  353.         return bp;
  354.     }
  355.     hdr->source.ssid &= ~E;
  356.     cp = putaxaddr(cp,&hdr->source);
  357.  
  358.     /* All but last digi get copied with E bit off */
  359.     for(i=0; i < hdr->ndigis - 1; i++){
  360.         hdr->digis[i].ssid &= ~E;
  361.         cp = putaxaddr(cp,&hdr->digis[i]);
  362.     }
  363.     hdr->digis[i].ssid |= E;
  364.     cp = putaxaddr(cp,&hdr->digis[i]);
  365.     return bp;
  366. }
  367. /* Convert an AX.25 ARP table entry into a host format address structure
  368.  * ready for use in transmitting a packet
  369.  */
  370. int
  371. atohax25(hdr,hwaddr,source)
  372. register struct ax25 *hdr;
  373. register char *hwaddr;
  374. struct ax25_addr *source;
  375. {
  376.     extern struct ax25_addr mycall;
  377.     register struct ax25_addr *axp;
  378.  
  379.     hwaddr = getaxaddr(&hdr->dest,hwaddr);    /* Destination address */
  380.     ASSIGN(hdr->source,*source);        /* Source address */
  381.     if(hdr->dest.ssid & E){
  382.         /* No digipeaters */
  383.         hdr->ndigis = 0;
  384.         hdr->dest.ssid &= ~E;
  385.         hdr->source.ssid |= E;
  386.         return 2;
  387.     }
  388.     hdr->source.ssid &= ~E;
  389.     hdr->dest.ssid &= ~E;
  390.     for(axp = hdr->digis; axp < &hdr->digis[MAXDIGIS]; axp++){
  391.         hwaddr = getaxaddr(axp,hwaddr);
  392.         if(axp->ssid & E){
  393.             hdr->ndigis = axp - hdr->digis + 1;
  394.             return hdr->ndigis;
  395.         }
  396.     }
  397.     return -1;
  398. }
  399. /* Convert a network-format AX.25 header into a host format structure
  400.  * Return -1 if error, number of addresses if OK
  401.  */
  402. int
  403. ntohax25(hdr,bpp)
  404. register struct ax25 *hdr;    /* Output structure */
  405. struct mbuf **bpp;
  406. {
  407.     register struct ax25_addr *axp;
  408.     char *getaxaddr();
  409.     char buf[AXALEN];
  410.  
  411.     if(pullup(bpp,buf,AXALEN) < AXALEN)
  412.         return -1;
  413.     getaxaddr(&hdr->dest,buf);
  414.  
  415.     if(pullup(bpp,buf,AXALEN) < AXALEN)
  416.         return -1;
  417.     getaxaddr(&hdr->source,buf);
  418.  
  419.     /* Process C bits to get command/response indication */
  420.     if((hdr->source.ssid & C) == (hdr->dest.ssid & C))
  421.         hdr->cmdrsp = UNKNOWN;
  422.     else if(hdr->source.ssid & C)
  423.         hdr->cmdrsp = RESPONSE;
  424.     else
  425.         hdr->cmdrsp = COMMAND;
  426.  
  427.     hdr->ndigis = 0;
  428.     if(hdr->source.ssid & E)
  429.         return 2;    /* No digis */
  430.  
  431.     /* Process digipeaters */
  432.     for(axp = hdr->digis;axp < &hdr->digis[MAXDIGIS]; axp++){
  433.         if(pullup(bpp,buf,AXALEN) < AXALEN)
  434.             return -1;
  435.         getaxaddr(axp,buf);
  436.         if(axp->ssid & E){    /* Last one */
  437.             hdr->ndigis = axp - hdr->digis + 1;
  438.             return hdr->ndigis + 2;            
  439.         }
  440.     }
  441.     return -1;    /* Too many digis */
  442. }
  443.  
  444. /* Figure out the frame type from the control field
  445.  * This is done by masking out any sequence numbers and the
  446.  * poll/final bit after determining the general class (I/S/U) of the frame
  447.  */
  448. int16
  449. ftype(control)
  450. register char control;
  451. {
  452.     if((control & 1) == 0)    /* An I-frame is an I-frame... */
  453.         return I;
  454.     if(control & 2)        /* U-frames use all except P/F bit for type */
  455.         return(control & ~PF);
  456.     else            /* S-frames use low order 4 bits for type */
  457.         return(control & 0xf);
  458. }
  459.  
  460.